package com.gk.study.interceptor;

import com.google.gson.Gson;
import com.gk.study.common.APIResponse;
import com.gk.study.common.ResponeCode;
import com.gk.study.entity.User;
import com.gk.study.entity.Admin;
import com.gk.study.permission.Access;
import com.gk.study.permission.AccessLevel;
import com.gk.study.service.UserService;
import com.gk.study.service.AdminService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;

/**
 * 只做接口验权
 */
@Component
public class AccessInterceptor implements HandlerInterceptor {

    private Logger logger = LoggerFactory.getLogger(AccessInterceptor.class);

    private final UserService userService;
    private final AdminService adminService;

    public AccessInterceptor(UserService userService, AdminService adminService) {
        this.userService = userService;
        this.adminService = adminService;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        //**********************验权代码*************************
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        Access access = method.getAnnotation(Access.class);
        if (access == null) {
            // 如果注解为null, 说明不需要拦截, 直接放过
            return true;
        }

        AccessLevel requiredLevel = access.level();
        
        // 管理员权限检查
        if(requiredLevel.getCode() == AccessLevel.ADMIN.getCode()) {
            String adminToken = request.getHeader("ADMINTOKEN");
            if(adminToken != null) {
                Admin admin = adminService.getAdminByToken(adminToken);
                if(admin != null && admin.getStatus() == 1){
                    return true;
                }
            }
            // 检查用户是否有管理员角色
            String userToken = request.getHeader("TOKEN");
            if(userToken != null) {
                User user = userService.getUserByToken(userToken);
                if(user != null && user.getStatus() == 1 && "admin".equals(user.getRole())){
                    return true;
                }
            }
            APIResponse apiResponse = new APIResponse(ResponeCode.FAIL, "需要管理员权限");
            writeResponse(response, apiResponse);
            return false;
        }

        // 登录用户权限检查
        if(requiredLevel.getCode() == AccessLevel.LOGIN.getCode()) {
            String token = request.getHeader("TOKEN");
            if(token != null) {
                User user = userService.getUserByToken(token);
                if(user != null && user.getStatus() == 1){
                    return true;
                }
            }
            APIResponse apiResponse = new APIResponse(ResponeCode.FAIL, "需要登录");
            writeResponse(response, apiResponse);
            return false;
        }

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 可选实现
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 不再记录操作日志
    }

    public void writeResponse(HttpServletResponse response, APIResponse apiResponse) throws IOException {
        response.setStatus(200);
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Cache-Control", "no-cache");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        Gson gson = new Gson();
        String jsonStr = gson.toJson(apiResponse);
        response.getWriter().println(jsonStr);
        response.getWriter().flush();
    }
}
